package com.nulldev.util.net.packets.npcrypt.demos;

import java.util.ArrayList;

import com.nulldev.util.io.MD5Utils;
import com.nulldev.util.java.JVMUtil;
import com.nulldev.util.net.IPUtil;
import com.nulldev.util.net.packets.NetInfoAdapter;
import com.nulldev.util.net.packets.NetPacket;
import com.nulldev.util.net.packets.PacketEvent;
import com.nulldev.util.net.packets.PacketManager;
import com.nulldev.util.net.packets.PacketMode;
import com.nulldev.util.net.tcp.TCPCore;
import com.nulldev.util.net.tcp.client.TCPClient;
import com.nulldev.util.net.tcp.server.TCPServer;
import com.nulldev.util.net.tcp.server.TCPServer.ServerConnection;
import com.nulldev.util.other.ByteUtils;

public class NPCryptCommunication {

	public static void main(String[] args) {
		final int port = IPUtil.nextFreePort();
		final TCPServer tcps = new TCPServer("NPCrypt Demo", "NPCrypt.DEMO", port) {
			
			@Override
			public void receive(TCPCore connection, String event, String payload, byte[] bytes, long length, final long readTime) {
				//JVMUtil.async_println(event);
				final NetPacket packet = PacketManager.parsePacket(this, connection, event, bytes, readTime);
				if (!packet.isGeneric()) {
					packet.server(packet.getData(), event, NetInfoAdapter.create(connection));	
					//for (final PacketEvent e : (ArrayList<PacketEvent>) this.registered_events.clone()) {
					//	e.onPacketGet(packet);
					//}
				}
			}
			
			@Override
			public void onServerConnection(final ServerConnection conn) {
				final boolean keys = conn.annouceServerKeys();
			}
		};
		tcps.start();
		final TCPClient tcpc = new TCPClient("NPCrypt Demo Client", "NPCrypt.DEMO") {
			
			@Override
			public void receive(String event, String payload, byte[] bytes, long count, final long readTime) {
				//JVMUtil.async_println(event);
				final NetPacket packet = PacketManager.parsePacket(this, null, event, bytes, readTime);
				if (!packet.isGeneric()) {
					packet.client(packet.getData(), event, NetInfoAdapter.create(this.getConnection()));
				}
			}
		};
		tcpc.updateHost("127.0.0.1", port);
		tcpc.start();
		if (tcpc.waitForConnection(1000)) {
			final boolean ok = tcpc.createKeyPair();
			System.out.println("Encryption Ready: " + ok);
			System.out.println("Public Key MD5: " + MD5Utils.getMD5Hex(tcpc.getPublicKey()));
			System.out.println("Private Key MD5: " + MD5Utils.getMD5Hex(tcpc.getPrivateKey()));
			if (ok) {
				JVMUtil.async_println("Sending partially encrypted packet...");
				final NetPacket def = PacketManager.fromID("test", "hello world, decrypted!");
				tcps.broadcastV3ENC(def);
				JVMUtil.async_println("Sending FULLY encrypted packet...");
				tcps.broadcastV3ENCF(def, NetInfoAdapter.create(tcps.getConnections().get(0)));
				JVMUtil.async_println("Sending FULLY encrypted to packet to the server...");
				def.preferBytePayload(true);
				tcpc.sendBlocking(
						def, PacketMode.STANDARD_V2_FULLY_ENCRYPTED, NetInfoAdapter.create(tcpc.getConnection()));
			}
		}
	}

}
